﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using mSpy.UI.Model;
using Microsoft.Crm.SdkTypeProxy;
using System.Threading;

namespace mSpy.UI.Views
{
    public partial class Connect : Form
    {
        const string SAVED_CONNECTIONS_FILE = @".\_saveddata\connections.xml";

        public Connect()
        {
            InitializeComponent();
            SetupBackgroundWorkers();
        }

        #region properties & private variables
        private CrmSdkWrapper _sdk = null;
        public CrmSdkWrapper Sdk
        {
            get { return _sdk; }
        }

        private List<string> _orgs = null;
        private BackgroundWorker _getSdkWorker = new BackgroundWorker();
        private BackgroundWorker _getOrgsWorker = new BackgroundWorker();
        #endregion

        private void SetupBackgroundWorkers()
        {
            _getOrgsWorker.DoWork += new DoWorkEventHandler(_getOrgsWorker_DoWork);
            _getOrgsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_getOrgsWorker_RunWorkerCompleted);
            
            _getSdkWorker.DoWork += new DoWorkEventHandler(_getSdkWorker_DoWork);
            _getSdkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_getSdkWorker_RunWorkerCompleted);
        }

        #region form event handlers
        private void Connect_Load(object sender, EventArgs e)
        {
            this.deploymentType.DataSource = DeploymentType.GetAll();
            this.serverName.DataSource = SavedConnection.GetSaved(SAVED_CONNECTIONS_FILE);
        }

        private void serverName_SelectedIndexChanged(object sender, EventArgs e)
        {
            var connection = this.serverName.SelectedItem as SavedConnection;
            this.domain.Text = connection.Domain;
            this.username.Text = connection.Username;
            this.password.Text = connection.Password;

            this.connectnow.Text = "Connect";
            this.selectconnection.Text = "&OK";

            ToggleControls(true, this.serverName, this.deploymentType, this.domain, this.username, this.password, this.connectnow, this.crmorgs, this.selectconnection);
        }

        private void connectnow_Click(object sender, EventArgs e)
        {
            #region validation
            if (string.IsNullOrEmpty(this.serverName.Text))
            {
                MessageBox.Show("Please enter your server name. eg: http://192.168.1.1:5555", 
                    "Insufficient information", MessageBoxButtons.OK);

                return;
            }

            if (string.IsNullOrEmpty(this.domain.Text) ||
                string.IsNullOrEmpty(this.username.Text) ||
                string.IsNullOrEmpty(this.password.Text))
            {
                MessageBox.Show("Please enter your credentials, domain name, username and your password.", 
                    "Insufficient information", MessageBoxButtons.OK);

                return;
            }
            #endregion

            ToggleControls(false, this.serverName, this.deploymentType, this.domain, this.username, this.password, this.connectnow, this.crmorgs, this.selectconnection);
            this.connectnow.Text = "Wait...";

            string url = this.serverName.Text + (this.deploymentType.SelectedItem as DeploymentType).DiscoveryUrl;
            _getOrgsWorker.RunWorkerAsync(new string[]
            {
                url, this.domain.Text, this.username.Text, this.password.Text
            });
        }

        private void selectconnection_Click(object sender, EventArgs e)
        {
            ToggleControls(false, this.serverName, this.selectconnection);
            this.selectconnection.Text = "Wait...";

            string url = this.serverName.Text + (this.deploymentType.SelectedItem as DeploymentType).DiscoveryUrl;
            _getSdkWorker.RunWorkerAsync(new string[]
                {
                    url, this.crmorgs.Text, this.domain.Text, this.username.Text, this.password.Text
                });
        }
        #endregion

        #region background workers
        void _getOrgsWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] args = e.Argument as string[];
            try
            {
                _orgs = Connection.GetCrmOrgs(args[0], args[1], args[2], args[3]);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Unexpected Error");
            }
        }

        void _getOrgsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (_orgs != null && _orgs.Count > 0)
            {
                this.crmorgs.DataSource = _orgs;

                ToggleControls(true, this.crmorgs, this.selectconnection, this.serverName); // we want to enable this so that a user can select a different server if needed
            }
            else
            {
                ToggleControls(true, this.serverName, this.deploymentType, this.domain, this.username, this.password, this.connectnow);
                this.connectnow.Text = "Connect";
            }
        }

        void _getSdkWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] args =e.Argument as string[];
            _sdk = Connection.GetCrmSdk(args[0], args[1], args[2], args[3], args[4]);
        }

        void _getSdkWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            SaveConnection();

            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }
        #endregion

        #region helper methods
        private void SaveConnection()
        {
            SavedConnection tosave = new SavedConnection
            {
                DeploymentType = (this.deploymentType.SelectedItem as DeploymentType),
                Domain = this.domain.Text,
                Organization = this.crmorgs.Text,
                Password = this.password.Text,
                Username = this.username.Text,
                ServerName = this.serverName.Text
            };
            tosave.Save(SAVED_CONNECTIONS_FILE);
        }

        private void ToggleControls(bool enable, params Control[] controls)
        {
            if (controls != null)
            {
                for (int i = 0; i < controls.Length; i++)
                {
                    controls[i].Enabled = enable;
                }
            }
        }
        #endregion
    }
}
